#ifndef GEMREN_INTERSECTION_H
#define	GEMREN_INTERSECTION_H
#include "globals.h"
#include "triangle.h"
#include "common/math/col3.h"
#include "color.h"
namespace gemren
{
	enum ray_origin { ro_other, ro_camera, ro_diffuse, ro_transmitted_diffuse };

	struct intersection : public embree::Hit
	{
		intersection():
			wavelength(-1.0f), 
			depth(3*EPSILON), 
			light(0.0f), 
			importance(1.0f),
			light_w(0.0f),
			importance_w(1.0f),
			rayorigin(ro_camera),
			from_inside(false), 
			diffuse_reflection(false), 
			lighting_mode(LM_PRIMARY_LIGHTSOURCE | LM_CAUSTIC_BRDF),
			mis_brdf_importance(1.0f), 
			reflectance(1.0f)
		{}
		triangle *triptr;
		coord normal;
		coord incoming, outcoming;
		coord abs_pos;
		bool from_inside;
		float depth;
		float mis_brdf_importance;
		unsigned int lighting_mode;

		size_t prevtri;
		bool diffuse_reflection;
		ray_origin rayorigin;
		float reflectance; //for russian roulette
		int max_depth;
		const embree::Col3f get_light(const color_converter& conv)const 
		{
			//return embree::Col3f(light.integral()+light_w);
			return wavelength < 0.0f ?
						conv.spectrum_to_col3(light)
						:
						conv.spectrum_to_col3(light) + conv.wavelength_color(wavelength) * light_w;	
		}

		void dim_light(const float f){
			if(wavelength<0.0f)
				importance *= f;
			else 
				importance_w *=f;
		}
		void dim_light(const spectrum& s){
			if(wavelength<0.0f)
				importance *= s;
			else 
				importance_w *= s[wavelength];
		}

		void add_light(const spectrum& l)
		{
			if(wavelength<0.0f)
				light += importance * l; 
			else
				light_w += importance_w *l[wavelength];
		}
		void add_light(const intersection& i)
		{
			if(wavelength<0)
			{
				light += importance*i.light;
				if(i.wavelength >= 0)
				{
					set_wavelength(i.wavelength);
					light_w += importance_w * i.light_w;
				}
			}
			else
			{
				light_w += importance_w * i.light[wavelength];
				if(wavelength == i.wavelength)
				{
					light_w += importance_w * i.light_w;
				}
			}
		}
		void blacken()
		{
			light = spectrum(0.0f);
		}
		void terminate()
		{
			max_depth = 0;
			reflectance = 0;
		}
		float get_wavelength() const { return wavelength; }
		void  set_wavelength(float wl)  
		{ 
			if(wl>=0.0f)
			{
				wavelength = wl;
				importance_w = importance[wl];
			}
		}
	protected:
		spectrum light;
		spectrum importance; //factor of incoming light
		float wavelength;
		float importance_w; //for monochrome light
		float light_w;
	};

}
#endif